#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>

#include "input.h"

#define INITIAL_INPUT_BUFFER_CAPACITY 160

char * input = 0;
size_t input_size = 0;
size_t input_capacity = 0;

void input_grow() {
    size_t old_byte_capacity = input_size * sizeof(char);

    //If already as large as can be, return
    if ( old_byte_capacity > SIZE_MAX - sizeof(char) )
        return;

    size_t new_capacity = input_capacity * 2;
    size_t new_byte_capacity = new_capacity * sizeof(char);

    //If byte capacities overflow or the new capacity is greater than SIZE_MAX
    if ( new_byte_capacity < old_byte_capacity || new_byte_capacity > SIZE_MAX ) {
        new_capacity = SIZE_MAX / sizeof(char);
        new_byte_capacity = new_capacity * sizeof(char);
    }

    char * new_input = realloc( input, new_byte_capacity );

    //If allocation failed, exit
    if ( new_input == NULL )
        exit(1);

    input = new_input;
}

void input_addChar( char c ) {
    if ( input_size == input_capacity )
        input_grow();

    //If allocation failed, exit
    if ( input_size == input_capacity )
        exit(1);

    //Else, add character
    input[input_size++] = c;
}

void input_clear() {
    input_size = 0;
}

int input_init()
{
    if ( ( input = malloc( sizeof(char) * INITIAL_INPUT_BUFFER_CAPACITY ) ) == 0 )
        return 1;

    input_capacity = INITIAL_INPUT_BUFFER_CAPACITY;
    return 0;
}

const char * input_read() {
    bool loop = true;

    while( loop )
    {
        char c = getchar();

        if ( c == '\n' )
            loop = false;
        else
            input_addChar( c );
        /*
        switch ( c ) {
            case '\n':
                if ( input_size != 0 && input[input_size - 1] != '\\' ) {
                    br = 1;
                    break;
                }
            default:
                input_addChar( c );
        }
        */
    }

    input_addChar( 0 );

    return input;
}
